import os
import importlib.util
import time
from contextlib import asynccontextmanager

from fastapi import FastAPI, Request, Response
from jose import JWTError, jwt

from core.config import settings
from core.logging_config import logger
from db.session import async_session
from extension.ext_redis import init_redis_pool, close_redis_pool
from models.request_log import RequestLog
from fastapi.middleware.cors import CORSMiddleware


@asynccontextmanager
async def lifespan(app: FastAPI):    # startup
    app.state.redis = await init_redis_pool()
    print("Redis connected!")

    yield  # 应用运行中

    # shutdown
    await close_redis_pool(app.state.redis)
    print("Redis closed!")


app = FastAPI(title="FastAPI Async RBAC Demo", lifespan=lifespan)


def set_cors(current_app):
    allow_origins_env = settings.ALLOW_ORIGINS  # 比如 "http://localhost:3000,http://127.0.0.1:3000" 或 "*"

    if allow_origins_env.strip() == "*":
        allow_origins = ["*"]
    else:
        # 拆分逗号，去掉多余空格
        allow_origins = [origin.strip() for origin in allow_origins_env.split(",")]

    current_app.add_middleware(
        CORSMiddleware,
        allow_origins=allow_origins,  # 允许的源
        allow_credentials=False if allow_origins == ["*"] else True,  # 允许携带cookie
        allow_methods=["*"],  # 允许的方法，比如 ["GET", "POST"]
        allow_headers=["*"],  # 允许的头部，比如 ["Authorization", "Content-Type"]
    )


set_cors(app)


# app.include_router(auth.router, prefix="/api")
# app.include_router(user.router, prefix="/api/users")
@app.middleware("http")
async def log_requests(request: Request, call_next):
    if request.method == "OPTIONS":
        return await call_next(request)

    start_time = time.time()
    response: Response = await call_next(request)
    process_time = int((time.time() - start_time) * 1000)

    username = None
    token = request.headers.get("Authorization")
    if token and token.startswith("Bearer "):
        try:
            payload = jwt.decode(token.split()[1], settings.SECRET_KEY, algorithms=["HS256"])
            username = payload.get("sub")  # 这里存用户ID，你也可以额外查用户名
        except JWTError:
            pass

    # 保存到数据库（异步 session）
    async with async_session() as db:
        # async with get_db() as db:  # 注意这里 get_db 是 async generator
        log = RequestLog(
            method=request.method,
            path=request.url.path,
            status_code=response.status_code,
            process_time=process_time,
            username=username,
        )
        db.add(log)
        await db.commit()

    logger.info(
        f"{request.method} {request.url.path} status={response.status_code} time={process_time}ms"
    )
    return response


def import_routers_from_directory(directory, prefix, app):
    # 遍历指定目录中的所有文件和子目录
    for root, dirs, files in os.walk(directory):
        for file in files:
            # 只处理.py文件且不是__init__.py
            if file.endswith('.py') and file != '__init__.py':
                # 构造模块路径（相对于项目的根目录）
                module_path = os.path.relpath(os.path.join(root, file), os.path.dirname(__file__))
                # 去掉.py后缀并替换路径分隔符为点，以形成Python模块名
                module_name = module_path.replace(os.sep, '.').rsplit('.', 1)[0]

                # 动态导入模块
                spec = importlib.util.find_spec(module_name)
                if spec is not None:
                    module = importlib.util.module_from_spec(spec)
                    spec.loader.exec_module(module)

                    # 假设每个router模块都有一个名为'router'的属性
                    if hasattr(module, 'router'):
                        # 将router添加到FastAPI应用中
                        app.include_router(module.router, prefix=prefix)
                        # app.include_router(module.router, prefix=prefix + '/' + file.replace(".py", ''))


console_dir = os.path.join(os.path.dirname(__file__), 'controllers/console')

# 导入routers文件夹中的所有router
import_routers_from_directory(console_dir, '/console/api', app)

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host='0.0.0.0', port=8080)
